bitkeeper revision 1.1159.179.12 (419e133foVH755X0bQ79WRObEybang)
authorcl349@arcadians.cl.cam.ac.uk <cl349@arcadians.cl.cam.ac.uk>
Fri, 19 Nov 2004 15:37:35 +0000 (15:37 +0000)
committercl349@arcadians.cl.cam.ac.uk <cl349@arcadians.cl.cam.ac.uk>
Fri, 19 Nov 2004 15:37:35 +0000 (15:37 +0000)
Add teardown_irq and update do_IRQ interface to match the Linux 2.6 one.

.rootkeys
linux-2.4.27-xen-sparse/arch/xen/kernel/irq.c
linux-2.4.27-xen-sparse/include/linux/irq.h [new file with mode: 0644]
linux-2.6.10-rc2-xen-sparse/arch/xen/kernel/evtchn.c

index 4152ff07fe8cdc4f5aa4d7562401727059bc4770..044186df4f0b6c81424ae2f397a3cf1bc37e4e2b 100644 (file)
--- a/.rootkeys
+++ b/.rootkeys
 3f1056a9L_kqHcFheV00KbKBzv9j5w linux-2.4.27-xen-sparse/include/asm-xen/vga.h
 40659defgWA92arexpMGn8X3QMDj3w linux-2.4.27-xen-sparse/include/asm-xen/xor.h
 3f056927gMHl7mWB89rb73JahbhQIA linux-2.4.27-xen-sparse/include/linux/blk.h
+419e0488SBzS3mdUhwgsES5a5e3abA linux-2.4.27-xen-sparse/include/linux/irq.h
 4124f66fPHG6yvB_vXmesjvzrJ3yMg linux-2.4.27-xen-sparse/include/linux/mm.h
 401c0590D_kwJDU59X8NyvqSv_Cl2A linux-2.4.27-xen-sparse/include/linux/sched.h
 40a248afgI0_JKthdYAe8beVfXSTpQ linux-2.4.27-xen-sparse/include/linux/skbuff.h
index 8154c5b7c397c10f1c80c8b342e15b7fbe255482..457ca3f553cbc0bef2836baeac8f230ae73f9a3c 100644 (file)
@@ -559,7 +559,7 @@ void enable_irq(unsigned int irq)
  * SMP cross-CPU interrupts have their own specific
  * handlers).
  */
-asmlinkage unsigned int do_IRQ(int irq, struct pt_regs *regs)
+asmlinkage unsigned int do_IRQ(struct pt_regs *regs)
 {      
        /* 
         * We ack quickly, we don't want the irq controller
@@ -571,6 +571,7 @@ asmlinkage unsigned int do_IRQ(int irq, struct pt_regs *regs)
         * 0 return value means that this irq is already being
         * handled by some other CPU. (or is disabled)
         */
+       int irq = regs->orig_eax & 0xff; /* high bits used in ret_from_ code */
        int cpu = smp_processor_id();
        irq_desc_t *desc = irq_desc + irq;
        struct irqaction * action;
@@ -731,32 +732,18 @@ int request_irq(unsigned int irq,
        return retval;
 }
 
-/**
- *     free_irq - free an interrupt
- *     @irq: Interrupt line to free
- *     @dev_id: Device identity to free
- *
- *     Remove an interrupt handler. The handler is removed and if the
- *     interrupt line is no longer in use by any driver it is disabled.
- *     On a shared IRQ the caller must ensure the interrupt is disabled
- *     on the card it drives before calling this function. The function
- *     does not return until any executing interrupts for this IRQ
- *     have completed.
- *
- *     This function may be called from interrupt context. 
- *
- *     Bugs: Attempting to free an irq in a handler for the same irq hangs
- *           the machine.
+/*
+ * Internal function to unregister an irqaction - typically used to
+ * deallocate special interrupts that are part of the architecture.
  */
-void free_irq(unsigned int irq, void *dev_id)
+int teardown_irq(unsigned int irq, struct irqaction * old)
 {
        irq_desc_t *desc;
        struct irqaction **p;
        unsigned long flags;
 
        if (irq >= NR_IRQS)
-               return;
+               return -ENOENT;
 
        desc = irq_desc + irq;
        spin_lock_irqsave(&desc->lock,flags);
@@ -766,7 +753,7 @@ void free_irq(unsigned int irq, void *dev_id)
                if (action) {
                        struct irqaction **pp = p;
                        p = &action->next;
-                       if (action->dev_id != dev_id)
+                       if (action != old)
                                continue;
 
                        /* Found it - now remove it from the list of entries */
@@ -784,15 +771,56 @@ void free_irq(unsigned int irq, void *dev_id)
                                cpu_relax();
                        }
 #endif
-#define SA_STATIC_ACTION 0x01000000 /* Is it our duty to free the action? */
-                       if (!(action->flags & SA_STATIC_ACTION))
-                               kfree(action);
-                       return;
+                       return 0;
                }
                printk("Trying to free free IRQ%d\n",irq);
                spin_unlock_irqrestore(&desc->lock,flags);
+               return -ENOENT;
+       }
+}
+
+/**
+ *     free_irq - free an interrupt
+ *     @irq: Interrupt line to free
+ *     @dev_id: Device identity to free
+ *
+ *     Remove an interrupt handler. The handler is removed and if the
+ *     interrupt line is no longer in use by any driver it is disabled.
+ *     On a shared IRQ the caller must ensure the interrupt is disabled
+ *     on the card it drives before calling this function. The function
+ *     does not return until any executing interrupts for this IRQ
+ *     have completed.
+ *
+ *     This function may be called from interrupt context. 
+ *
+ *     Bugs: Attempting to free an irq in a handler for the same irq hangs
+ *           the machine.
+ */
+void free_irq(unsigned int irq, void *dev_id)
+{
+       irq_desc_t *desc;
+       struct irqaction *action;
+       unsigned long flags;
+
+       if (irq >= NR_IRQS)
+               return;
+
+       desc = irq_desc + irq;
+       spin_lock_irqsave(&desc->lock,flags);
+       for (action = desc->action; action != NULL; action = action->next) {
+               if (action->dev_id != dev_id)
+                       continue;
+
+               spin_unlock_irqrestore(&desc->lock,flags);
+
+               if (teardown_irq(irq, action) == 0)
+                       kfree(action);
                return;
        }
+       printk("Trying to free free IRQ%d\n",irq);
+       spin_unlock_irqrestore(&desc->lock,flags);
+       return;
 }
 
 /*
diff --git a/linux-2.4.27-xen-sparse/include/linux/irq.h b/linux-2.4.27-xen-sparse/include/linux/irq.h
new file mode 100644 (file)
index 0000000..7052672
--- /dev/null
@@ -0,0 +1,80 @@
+#ifndef __irq_h
+#define __irq_h
+
+/*
+ * Please do not include this file in generic code.  There is currently
+ * no requirement for any architecture to implement anything held
+ * within this file.
+ *
+ * Thanks. --rmk
+ */
+
+#include <linux/config.h>
+
+#if !defined(CONFIG_ARCH_S390)
+
+#include <linux/cache.h>
+#include <linux/spinlock.h>
+
+#include <asm/irq.h>
+#include <asm/ptrace.h>
+
+/*
+ * IRQ line status.
+ */
+#define IRQ_INPROGRESS 1       /* IRQ handler active - do not enter! */
+#define IRQ_DISABLED   2       /* IRQ disabled - do not enter! */
+#define IRQ_PENDING    4       /* IRQ pending - replay on enable */
+#define IRQ_REPLAY     8       /* IRQ has been replayed but not acked yet */
+#define IRQ_AUTODETECT 16      /* IRQ is being autodetected */
+#define IRQ_WAITING    32      /* IRQ not yet seen - for autodetection */
+#define IRQ_LEVEL      64      /* IRQ level triggered */
+#define IRQ_MASKED     128     /* IRQ masked - shouldn't be seen again */
+#define IRQ_PER_CPU    256     /* IRQ is per CPU */
+
+/*
+ * Interrupt controller descriptor. This is all we need
+ * to describe about the low-level hardware. 
+ */
+struct hw_interrupt_type {
+       const char * typename;
+       unsigned int (*startup)(unsigned int irq);
+       void (*shutdown)(unsigned int irq);
+       void (*enable)(unsigned int irq);
+       void (*disable)(unsigned int irq);
+       void (*ack)(unsigned int irq);
+       void (*end)(unsigned int irq);
+       void (*set_affinity)(unsigned int irq, unsigned long mask);
+};
+
+typedef struct hw_interrupt_type  hw_irq_controller;
+
+/*
+ * This is the "IRQ descriptor", which contains various information
+ * about the irq, including what kind of hardware handling it has,
+ * whether it is disabled etc etc.
+ *
+ * Pad this out to 32 bytes for cache and indexing reasons.
+ */
+typedef struct {
+       unsigned int status;            /* IRQ status */
+       hw_irq_controller *handler;
+       struct irqaction *action;       /* IRQ action list */
+       unsigned int depth;             /* nested irq disables */
+       spinlock_t lock;
+} ____cacheline_aligned irq_desc_t;
+
+extern irq_desc_t irq_desc [NR_IRQS];
+
+#include <asm/hw_irq.h> /* the arch dependent stuff */
+
+extern int handle_IRQ_event(unsigned int, struct pt_regs *, struct irqaction *);
+extern int setup_irq(unsigned int , struct irqaction * );
+extern int teardown_irq(unsigned int , struct irqaction * );
+
+extern hw_irq_controller no_irq_type;  /* needed in every arch ? */
+extern void no_action(int cpl, void *dev_id, struct pt_regs *regs);
+
+#endif
+
+#endif /* __irq_h */
index ba58bdd973570974422a6396275a6414bc3f75cb..e5aa5a1b183971f1f35a62252d1e494d23327b05 100644 (file)
@@ -69,7 +69,11 @@ static unsigned long pirq_needs_unmask_notify[NR_PIRQS/sizeof(unsigned long)];
 
 /* Upcall to generic IRQ layer. */
 #ifdef CONFIG_X86
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,9)
 extern fastcall unsigned int do_IRQ(struct pt_regs *regs);
+#else
+extern asmlinkage unsigned int do_IRQ(struct pt_regs *regs);
+#endif
 #define do_IRQ(irq, regs) do {         \
     (regs)->orig_eax = (irq);          \
     do_IRQ((regs));                    \